#include "CFileProxy.h"
//---------------------------------------------------------------------------------------------
// CFileProxy
//---------------------------------------------------------------------------------------------
CFileProxy::CFileProxy(char *host, int port)
{
	repository_path = COORD_CONF_TMP_PATH;

	file_proxy = new CFactoryProxy();

	char tmp_url[256];
	sprintf(tmp_url, "http://%s:%d", host, port);
	url = tmp_url;

	// set server url
	// -----------------------------------------------
	file_proxy->soap_endpoint = (char *) url.c_str();
	// -----------------------------------------------

	file_proxy->imode = SOAP_ENC_MTOM;
	file_proxy->omode = SOAP_ENC_MTOM;

	//file_proxy->accept_flags |= SO_NOSIGPIPE;
	//file_proxy->socket_flags |= MSG_NOSIGNAL;

	file_proxy->connect_timeout = 10;

	// disable timeout for send/recv
	file_proxy->send_timeout = 0;
	file_proxy->recv_timeout = 0;


	mime = new CMIMEClientCallback();

	//-----------------------------------------------------
	// mime client handler
	//-----------------------------------------------------
	file_proxy->fmimereadopen = dynamic_cast<CMIMEClientCallback *>(mime)->read_open;
	file_proxy->fmimereadclose = dynamic_cast<CMIMEClientCallback *>(mime)->read_close;
	file_proxy->fmimeread = dynamic_cast<CMIMEClientCallback *>(mime)->read;
	file_proxy->fmimewriteopen = dynamic_cast<CMIMEClientCallback *>(mime)->write_open;
	file_proxy->fmimewrite = dynamic_cast<CMIMEClientCallback *>(mime)->write;
	file_proxy->fmimewriteclose = dynamic_cast<CMIMEClientCallback *>(mime)->write_close;
	//-----------------------------------------------------
}

CFileProxy::~CFileProxy()
{
	soap_dealloc((struct soap *)file_proxy, NULL);
	soap_delete((struct soap *)file_proxy, NULL);
	soap_destroy((struct soap *)file_proxy);
	soap_end((struct soap *)file_proxy);
	soap_done((struct soap *)file_proxy);

	delete file_proxy;

	delete mime;
}

int CFileProxy::repository(char *r_path)
{
	repository_path = r_path;

	return 1;
}

string &CFileProxy::replace_file_path(string &path, string &file)
{
	CFile file_util;
	file_util.normalize_file_path(path);

	// concatenate only file name
	string::size_type pos = file.find_last_of("/"); // only file name
	if(pos!=string::npos) path += file.substr(pos+1);
	else path += file;

	return path;
}

/**
 * make MTOM header with file size, file name, and file mime type
 * and open the local file to read data
 * after then, CMIMEClientCallback will be performed.
 */
int CFileProxy::parameterize(const char *file, const char *repository_path, struct cubex__Data *data)
{
	if(access(file, F_OK)!=0) {
		cerr << "ERROR : there is no " << file << endl;

		((struct soap *)file_proxy)->error = SOAP_EOF;
		return ((struct soap *)file_proxy)->error; 
	}

	struct stat sb;
	FILE *fd = NULL;
	int size;

	soap_default_cubex__Data((struct soap *)file_proxy, data);

	// File size is unknown, so must use HTTP chunking and set size = 0
	soap_set_omode((struct soap *)file_proxy, SOAP_IO_CHUNK);
	size = 0;
	data->xop__Include.__size = size;

	// set the file to read on the client side
	//-----------------------------------------------------------------
	// __ptr is "handle" at the CMIMEClientCallback::read_open()
	// if NULL, callback will be just skipped
	data->xop__Include.__ptr = (unsigned char *) soap_strdup((struct soap *)file_proxy, file);
	//-----------------------------------------------------------------

	CFile fileman;
	data->xmlmime__contentType = soap_strdup((struct soap*)file_proxy, (char *)fileman.mime_type(file));
	data->xop__Include.type = data->xmlmime__contentType;

	// set the file to save on the server side
	//-----------------------------------------------------------------
	// id is "id" at the CMIMEServerCallback::write_open()
	//if NULL, CID automatically generated by gSOAP engine
	//-----------------------------------------------------------------
	string local_file = file;
	string remote_file = repository_path;
	replace_file_path(remote_file, local_file);
	
	data->xop__Include.id = soap_strdup((struct soap *)file_proxy, (char *)remote_file.c_str());
	//-----------------------------------------------------------------

	data->xop__Include.options = NULL;

	return SOAP_OK;
}

int CFileProxy::put(char *file)
{
	int i;
	struct cubex__DataSet data;
	struct cubex__putResponse response;

	data.__size = 1;
	data.item = (struct cubex__Data *) soap_malloc((struct soap *)file_proxy, 1 * sizeof(struct cubex__Data));

	if(parameterize(file, repository_path.c_str(), &data.item[0])==SOAP_EOF) {
		((struct soap *)file_proxy)->error = SOAP_EOF;
		return ((struct soap *)file_proxy)->error; 
	}

	if(file_proxy->put(&data, &response)) {
		soap_print_fault((struct soap *)file_proxy, stderr);
		((struct soap *)file_proxy)->error = SOAP_EOF;
		return ((struct soap *)file_proxy)->error;
	}
	else {
		for(i=0;i<response.__keys.__size;i++) {
#ifdef DEBUG
			cerr << response.__keys.key[i] << endl;
#endif
		}
		return 1;
	}
}

int CFileProxy::get(char *file)
{
	int i;
	struct cubex__Keys keys;
	struct cubex__getResponse response;

	//-------------------------------------------------------------------------------
	// get only one file
	//-------------------------------------------------------------------------------
	keys.__size = 1;
	keys.key = (char **) soap_malloc((struct soap *)file_proxy, 1 * sizeof(char *));
	//keys.key = (char **) soap_malloc((struct soap *)file_proxy, 1 * sizeof(char **));

	keys.key[0] = soap_strdup((struct soap *)file_proxy, file);
	//-------------------------------------------------------------------------------

	// set repository to get remote files
	keys.repository = soap_strdup((struct soap *)file_proxy, (char *)repository_path.c_str());

	if(file_proxy->get(&keys, &response)) {
		soap_print_fault((struct soap *)file_proxy, stderr);
		((struct soap *)file_proxy)->error = SOAP_EOF;
		return ((struct soap *)file_proxy)->error;
	}
	else {
#ifdef DEBUG
		cerr << file << endl;
#endif
		return 1;
	}
}
